#pragma once
#include<vector>
#include<string>
#include<algorithm>
class Buffer
{
    public:
        static const size_t kCheapPrepend=8;//数据包前端预留8个字节
        static const size_t kInitialSize=1024;//初始的缓冲区的长度1kb

        explicit Buffer(size_t initialSize =kInitialSize)
            :buffer_(kCheapPrepend+initialSize)
            ,readerIndex_(kCheapPrepend)
            ,writerIndex_(kCheapPrepend)
            {}

        size_t readableBytes() const //返回当前可读数据的字节数，用于判断是否收到完整消息
        {
            return writerIndex_-readerIndex_;
        }

        size_t writableBytes() const //返回当前可写空间，用于判断是否需要扩容；
        {
            return buffer_.size()-writerIndex_;
        }

        size_t prependableBytes() const  //返回“已读区域”的大小，即 readerIndex_ 前面的空间，这部分空间可以被 makespace() 时复用；
        {
            return readerIndex_;
        }

        const char* peek() const//返回缓冲区中可读数据的起始地址
        {
            return begin() +readerIndex_;
        }
        //

        void retrieve(size_t len)//用于管理缓冲区读位置的关键方法，主要作用是在数据被读取后更新读指针位置：
        {
            if(len<readableBytes())//读的长度小于总的长度
            {
                readerIndex_+=len;
            }
            else//读完了
            {
                retrieveAll();
            }
        }

        void retrieveAll()
        {
            readerIndex_=writerIndex_=kCheapPrepend;
        }
        //将onMessage函数上报的BUffer数据转成string类型的数据返回给我们用
        std::string retrieveAllAsString()
        {
            return retrieveAsString(readableBytes());//应用可读取的长度
        }

        std::string retrieveAsString(size_t len)
        {
            std::string result(peek(),len);
            retrieve(len);//上面一句已经把缓冲区中要读的可读数据已经读走，接下来要将可读的数据重新定位开头。
            return result;
        }
        void ensureWriteableBytes(size_t len)
        {
            if(writableBytes()<len)//要写的大于可写的缓冲区，要进行扩容
            {
                makespace(len);
            }
        }
         //把[data,data+len]中的数据放在writable缓冲区中
         void append(const char *data,size_t len)
         {
             ensureWriteableBytes(len);
             std::copy(data,data+len,beginWrite());
             writerIndex_+=len;
         }

         char* beginWrite()
         {
             return begin()+writerIndex_;
         }
         const char* beginWrite() const
         {
             return begin()+writerIndex_;
         }
        
         //从fd上读取数据
         ssize_t readFd(int fd,int* saveError);
         ssize_t writeFd(int fd,int* saveErrno);
         
    private:
        char* begin()
        {
            return &*buffer_.begin();//vector底层数组首元素的起始地址，也就是数组的起始地址
        }
        const char* begin() const
        {
            return &*buffer_.begin();//vector底层数组首元素的起始地址，也就是数组的起始地址
        }
        void makespace(size_t len)//内存管理
        {
            if(writableBytes()+prependableBytes()<len+kCheapPrepend)//即使把前面空闲空间腾出来，也不够用
            {
                buffer_.resize(writerIndex_+len);
            }
            else//读过的区域空闲下来了
            {
                size_t readable=readableBytes();
                //把可读数据从 readerIndex_ 搬到 kCheapPrepend 开头
                std::copy(begin()+readerIndex_,
                            begin()+writerIndex_,
                        begin()+kCheapPrepend);
                readerIndex_=kCheapPrepend;
                writerIndex_=readerIndex_+readable;
            }
        }

        std::vector<char> buffer_;//真正的数据存储区
        size_t readerIndex_;//下一个可读字节的位置
        size_t writerIndex_;//下一个可写字节的位置
};